home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_092 / as6502 / assm1.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  10KB  |  437 lines

  1. /*    As6502 main routine: assm1.c     */
  2.  
  3. #include "stdio.h"
  4. #include "ctype.h"
  5. #include "assm.d1"
  6. #include "assm.d2"
  7. #include <time.h>
  8.  
  9. #define CPMEOF EOF
  10.  
  11. /*  Version 5.0 ported to the Amiga 3/1/87 by Joel Swank                */
  12.  
  13. /*  Version 5.0 is a major revision by Joel Swank. It adds the following
  14.  *  features: '.PAGE' pseudo with optional title; automatic paging and
  15.  *  -p flag to specify page length; A sorted symbol cross reference;
  16.  *  -t flag to specify the symbol table size; -w flag to specify the width
  17.  *  of a listing line. The -m option causes the object file to be formatted
  18.  *  as a standard MOS Technology object file. Also added error checking
  19.  *  and error messages to the argument parsing routine.
  20.  */
  21.  
  22. /*
  23.  *  Two changes to version 1.4 have been made to "port" as6502 to CP/M(tm).
  24.  *  A "tolower()" function call was add to the command line processing
  25.  *  code to (re)map the command line arguments to lower case (CP/M
  26.  *  converts all command line arguments to upper case).  The readline()
  27.  *  function has code added to "ignore" the '\r' character (CP/M includes
  28.  *  the \r character along with \n).
  29.  *
  30.  *  Also, the ability to process multiple files on the command line has been
  31.  *  added.  Now one can do, for example:
  32.  *
  33.  *    as6502 -nisvo header.file source.file data.file ...
  34.  *
  35.  *    George V. Wilder
  36.  *    IX 1A-360 x1937
  37.  *    ihuxp!gvw1
  38.  */
  39.  /*   Had to take out tolower call to work on 4.2bsd.  Joel Swank 5/9/85 */
  40.  /*   Added USAGE message in place of Invalid count message JS 12/2/86   */
  41.  
  42.  
  43. int    badflag;
  44. int    act;
  45. char    **avt;
  46.  
  47. main(argc, argv)
  48.    int    argc;
  49.    char *argv[];
  50. {
  51.     char    *malloc();
  52.     int    cnt;
  53.     int    i;
  54.     int    ac;
  55.     char    **av;
  56.     long    l;
  57.     size = STABSZ;
  58.     pagesize = PAGESIZE;
  59.     linesize = LINESIZE;
  60.     getargs(argc, argv);  /*   parse the command line arguments   */
  61.     if (badflag > 0) exit(1);
  62.     if (act == 0) {
  63.         fprintf(stderr, "USAGE: as6502 -[milnosv] [-p -t -w] file ...\n");
  64.         exit(1);
  65.     }
  66.     symtab = malloc(size);
  67.     if (symtab == 0) {
  68.         fprintf(stderr,"Symbol table allocation failed - specify a smaller size\n");
  69.         exit(2);  }
  70.     time(&l);
  71.     date = ctime(&l);
  72.     date[24] = '\0';
  73.     pagect = 0;
  74.     paglin = pagesize;
  75.     titlesize = linesize-36;
  76.     for (i=0 ; i<100; i++) titlbuf[i] = ' ';
  77.     titlbuf[titlesize] = '\0';
  78.     for (i=0 ; i<linesize-58; i++) syspc[i] = ' ';
  79.     syspc[i] = '\0';
  80.     ac = act;
  81.     av = avt;
  82.     pass = FIRST_PASS;
  83.     errcnt = loccnt = slnum = 0;
  84.     fprintf(stderr,"Initialization complete\n");
  85.     while (pass != DONE) {
  86.         initialize(ac, av, act);
  87.         fprintf(stderr,"PASS %d %s\n",pass+1,*av);
  88.         if(pass == LAST_PASS && ac == act)
  89.             errcnt = loccnt = slnum = 0;
  90.         /* lower level routines can terminate assembly by setting
  91.            pass = DONE  ('symbol table full' does this)   */
  92.         while (readline() != -1 && pass != DONE)
  93.             assemble(); /* rest of assembler executes from here */
  94.         if (errcnt != 0) {
  95.             pass = DONE;
  96.             fprintf(stderr, "Terminated with error counter = %d\n", errcnt);
  97.         }
  98.         switch (pass) {
  99.         case FIRST_PASS:
  100.             --ac;
  101.             ++av;
  102.             if(ac == 0) {
  103.                 pass = LAST_PASS;
  104.                 if (lflag == 0)
  105.                     lflag++;
  106.                 ac = act;
  107.                 av = avt;
  108.             }
  109.             break;
  110.         case LAST_PASS:
  111.             --ac;
  112.             ++av;
  113.             if(ac == 0) {
  114.                 pass = DONE;
  115.                 if (sflag != 0)
  116.                     stprnt();
  117.             }
  118.         }
  119.         wrapup();
  120.         if ((dflag != 0) && (pass == LAST_PASS)) {
  121.             fprintf(stdout, "nxt_free = %d\n", nxt_free);
  122.             cnt = 0;
  123.         }
  124.     }
  125.     fclose(stdout);
  126.     free(symtab);
  127.     return(0);
  128. }
  129.  
  130. /*****************************************************************************/
  131.  
  132. /*   parse the command args and save data   */
  133.  
  134. getargs(argc,argv)
  135.    int    argc;
  136.    char *argv[];
  137. {
  138.     int    i;
  139.     char     c;
  140.     int     sz;
  141.     while (--argc > 0 && (*++argv)[0] == '-') {
  142.         for (i = 1; (c = (*argv)[i]) != '\0'; i++) {
  143.             switch (c) {
  144.             case 'd':        /* debug flag */
  145.                 dflag++;
  146.                 break;
  147.             case 'i':        /* ignore .nlst flag */
  148.                 iflag++;
  149.                 break;
  150.             case 'l':        /* disable listing flag */
  151.                 lflag--;
  152.                 break;
  153.             case 'n':        /* normal/split address mode */
  154.                 nflag++;
  155.                 break;
  156.             case 'o':        /* object output flag */
  157.                 oflag++;
  158.                 break;
  159.             case 'm':        /* MOS Tech. object format  */
  160.                 mflag++;
  161.                 oflag++;    /* -m implies -o     */
  162.                 break;
  163.             case 's':        /* list symbol table flag */
  164.                 sflag++;
  165.                 break;
  166.             case 'v':        /* print assembler version */
  167.                 fprintf(stderr,
  168.                 "as6502 - Amiga version 5.0 - 3/1/87 - JHV [gvw,jhs]\n");
  169.                 break;
  170.             case 't':           /* input symbol table size */
  171.                 {
  172.                 if ((*argv)[++i] == '\0') {
  173.                     ++argv;
  174.                     argc--;
  175.                     sz = atoi(*argv);
  176.                     } else sz = atoi(&(*argv)[i]);
  177.                 if (sz>1000) size=sz;
  178.                 else {
  179.                      fprintf(stderr,
  180.                      "Invalid Symbol table size - minimum is 1000\n");
  181.                      badflag++; }
  182.                 goto outofloop;
  183.                 }
  184.             case 'p':           /* input lines per page */
  185.                 {
  186.                 if ((*argv)[++i] == '\0') {
  187.                     ++argv;
  188.                     argc--;
  189.                     sz = atoi(*argv);
  190.                     } else sz = atoi(&(*argv)[i]);
  191.                 if (sz>10 || sz == 0) pagesize=sz;
  192.                 else {
  193.                      fprintf(stderr,
  194.                      "Invalid Pagesize - minimum is 10\n");
  195.                      badflag++; }
  196.                 goto outofloop;
  197.                 }
  198.             case 'w':           /* input characters per line */
  199.                 {
  200.                 if ((*argv)[++i] == '\0') {
  201.                     ++argv;
  202.                     argc--;
  203.                     sz = atoi(*argv);
  204.                     } else sz = atoi(&(*argv)[i]);
  205.                 if (sz >= 80 && sz < 133) linesize=sz;
  206.                 else {
  207.                      fprintf(stderr,
  208.                      "Invalid Linesize - min is 80, max is 133\n");
  209.                      badflag++; }
  210.                 goto outofloop;
  211.                 }
  212.             default:
  213.             fprintf(stderr,"Unknown flag '%c'\n",c);
  214.             badflag++;
  215.             } /* end switch */
  216.         } /* end for  */
  217.         outofloop: ;
  218.     }
  219.     act=argc;   /* return values to main */
  220.     avt=argv;
  221. }
  222. /*****************************************************************************/
  223.  
  224. /* initialize opens files */
  225.  
  226. initialize(ac, av, argc)
  227.    int    ac;
  228.    char *av[];
  229.    int  argc;
  230. {
  231.  
  232.     if ((iptr = fopen(*av, "r")) == NULL) {
  233.         fprintf(stderr, "Open error for file '%s'.\n", *av);
  234.         exit(1);
  235.     }
  236.     if ((pass == LAST_PASS) && (oflag != 0) && ac == argc) {
  237.         if ((optr = fopen("6502.out", "w")) == NULL) {
  238.             fprintf(stderr, "Create error for object file 6502.out.\n");
  239.             exit(1);
  240.         }
  241.     }
  242. }
  243.  
  244. /* readline reads and formats an input line    */
  245.  
  246. int    field[] =
  247. {
  248.     SFIELD,
  249.     SFIELD + 8,
  250.     SFIELD + 14,
  251.     SFIELD + 23,
  252.     SFIELD + 43,
  253.     SFIELD + 75
  254. };
  255.  
  256. readline()
  257. {
  258.     int    i;        /* pointer into prlnbuf */
  259.     int    j;        /* pointer to current field start    */
  260.     int    ch;        /* current character        */
  261.     int    cmnt;        /* comment line flag    */
  262.     int    spcnt;        /* consecutive space counter    */
  263.     int    string;        /* ASCII string flag    */
  264.     int    temp1;        /* temp used for line number conversion */
  265.  
  266.     temp1 = ++slnum;
  267.     clrlin();
  268.     i = 3;
  269.     while (temp1 != 0) {    /* put source line number into prlnbuf */
  270.         prlnbuf[i--] = temp1 % 10 + '0';
  271.         temp1 /= 10;
  272.     }
  273.     i = SFIELD;
  274.     cmnt = spcnt = string = 0;
  275.     j = 1;
  276.     while ((ch = getc(iptr)) != '\n') {
  277.         if(ch == '\r')
  278.             continue;
  279.         prlnbuf[i++] = ch;
  280.         if ((ch == ' ') && (string == 0)) {
  281.             if (spcnt != 0)
  282.                 --i;
  283.             else if (cmnt == 0) {
  284.                 ++spcnt;
  285.                 if (i < field[j])
  286.                     i = field[j];
  287.                 if (++j > 3) {
  288.                     spcnt = 0;
  289.                     ++cmnt;
  290.                 }
  291.             }
  292.         }
  293.         else if (ch == '\t') {
  294.             prlnbuf[i - 1] = ' ';
  295.             spcnt = 0;
  296.             if (cmnt == 0) {
  297.                 if (i < field[j])
  298.                     i = field[j];
  299.                 if (++j > 3)
  300.                     ++cmnt;
  301.             }
  302.             else i = (i + 8) & 0x78;
  303.         }
  304.         else if ((ch == ';') && (string == 0)) {
  305.             spcnt = 0;
  306.             if (i == SFIELD + 1)
  307.                 ++cmnt;
  308.             else if (prlnbuf[i - 2] != '\'') {
  309.                 ++cmnt;
  310.                 prlnbuf[i-1] = ' ';
  311.                 if (i < field[3])
  312.                     i = field[3];
  313.                 prlnbuf[i++] = ';';
  314.             }
  315.         }
  316.         else if (ch == EOF || ch == CPMEOF)
  317.             return(-1);
  318.         else {
  319.             if ((ch == '"') && (cmnt == 0))
  320.                 string = string ^ 1;
  321.             spcnt = 0;
  322.             if (i >= LAST_CH_POS - 1)
  323.                 --i;
  324.         }
  325.     }
  326.     prlnbuf[i] = 0;
  327.     return(0);
  328. }
  329.  
  330. /*
  331.  * wrapup() closes the source, object and stdout files
  332.  */
  333.  
  334. wrapup()
  335. {
  336.  
  337.     fclose(iptr); /* close source file */
  338.     if (pass == DONE) {
  339.         if ((oflag != 0) && (optr !=0)) {
  340.             if (mflag != 0) fin_obj();
  341.             else fputc('\n', optr);
  342.             fclose(optr);
  343.         }
  344.     }
  345.     return;
  346. }
  347.  
  348. /* symbol table print
  349.  */
  350.  
  351. stprnt()
  352. {
  353.     int    i;        /* print line position */
  354.     int    ptr;        /* symbol table position */
  355.     int    j;        /* integer conversion variable */
  356.     int    k;        /* printf buffer pointer */
  357.     int    refct;        /* counter for references  */
  358.     char    buf[6];
  359.     paglin = pagesize;
  360.     ptr = 0;
  361.     clrlin();
  362.     while (ptr < nxt_free)
  363.         {
  364.         for (i=1; i <= symtab[ptr]; i++) prlnbuf[i] = symtab[ptr+i];
  365.         ptr += i+1; i=23;         /* value at pos 23  */
  366.         j = symtab[ptr++] & 0xff;
  367.         j += (symtab[ptr++] << 8);
  368.         hexcon(4,j);
  369.         if (nflag == 0) {
  370.             i--;
  371.             prlnbuf[i++] = hex[3];
  372.             prlnbuf[i++] = hex[4];
  373.             prlnbuf[i++] = ':';
  374.             prlnbuf[i++] = hex[1];
  375.             prlnbuf[i++] = hex[2]; }
  376.         else for (k=1; k<5; k++) prlnbuf[i++] = hex[k];
  377.         j = symtab[ptr++] & 0xff;
  378.         j += (symtab[ptr++] << 8);
  379.         sprintf(buf,"%d",j);
  380.         k=0;i=30;        /* line defined at pos 30 */
  381.         while (buf[k] != '\0') prlnbuf[i++] = buf[k++];
  382.         k=0;i=37;        /* count of references    */
  383.         refct = symtab[ptr++] & 0xff;
  384.         sprintf(buf,"(%d)",refct);
  385.         while (buf[k] != '\0') prlnbuf[i++] = buf[k++];
  386.         i++;            /* and all the references   */
  387.         while (refct > 0)
  388.             {
  389.             j = symtab[ptr++] & 0xff;
  390.             j += (symtab[ptr++] << 8);
  391.             sprintf(buf,"%d",j);
  392.             k=0;
  393.             while (buf[k] != '\0') prlnbuf[i++] = buf[k++];
  394.             i++;
  395.             refct--;
  396.             if ( i > linesize-5 && refct > 0) {
  397.                 prlnbuf[i] = '\0';
  398.                 prsyline(); i=37; }
  399.             }
  400.         prlnbuf[i] = '\0';
  401.         prsyline();
  402.         }
  403.  
  404. }
  405. /* prsyline prints the contents of prlnbuf */
  406.  
  407. prsyline()
  408. {
  409.     if (paglin == pagesize) prsymhead();
  410.     prlnbuf[linesize] = '\0';
  411.     fprintf(stdout, "%s\n", prlnbuf);
  412.     paglin++ ;
  413.     clrlin();
  414. }
  415.  
  416. /****************************************************************************/
  417.  
  418. /* prsymhead prints the page heading   */
  419.  
  420. prsymhead()
  421. {
  422.     if (pagesize == 0) return;
  423.     pagect++ ;
  424.     fprintf(stdout, "\f\nAmiga 6502 assembler :  Symbol Cross Reference - %s PAGE %d\n",syspc,pagect);
  425.     fprintf(stdout, "Symbol                Value Defined References\n\n");
  426.     paglin = 0;
  427. }
  428.  
  429. /*    clear the print buffer      */
  430.  
  431. clrlin()
  432. {
  433.     int i;
  434.     for (i = 0; i < LAST_CH_POS; i++)
  435.         prlnbuf[i] = ' ';
  436. }
  437.